import { useFlag, useParams } from 'common' import { ExternalLink, RefreshCw, Search, X } from 'lucide-react' import { useRouter } from 'next/router' import { parseAsString, parseAsStringLiteral, useQueryState } from 'nuqs' import React, { useMemo, useRef } from 'react' import { Button, Card, Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from 'ui' import { Admonition } from 'ui-patterns' import { Input } from 'ui-patterns/DataInputs/Input' import { PageContainer } from 'ui-patterns/PageContainer' import { PageHeader, PageHeaderAside, PageHeaderDescription, PageHeaderMeta, PageHeaderSummary, PageHeaderTitle, } from 'ui-patterns/PageHeader' import { PageSection, PageSectionContent } from 'ui-patterns/PageSection' import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader' import { DeployEdgeFunctionButton } from '@/components/interfaces/EdgeFunctions/DeployEdgeFunctionButton' import { EDGE_FUNCTIONS_SORT_VALUES, EdgeFunctionsSort, EdgeFunctionsSortColumn, EdgeFunctionsSortDropdown, EdgeFunctionsSortOrder, } from '@/components/interfaces/EdgeFunctions/EdgeFunctionsSortDropdown' import { EdgeFunctionsListItem } from '@/components/interfaces/Functions/EdgeFunctionsListItem' import { FunctionsEmptyState, FunctionsInstructionsLocal, } from '@/components/interfaces/Functions/FunctionsEmptyState' import { TerminalInstructionsDialog } from '@/components/interfaces/Functions/TerminalInstructionsDialog' import { useFunctionsListShortcuts } from '@/components/interfaces/Functions/useFunctionsListShortcuts' import DefaultLayout from '@/components/layouts/DefaultLayout' import EdgeFunctionsLayout from '@/components/layouts/EdgeFunctionsLayout/EdgeFunctionsLayout' import AlertError from '@/components/ui/AlertError' import { DocsButton } from '@/components/ui/DocsButton' import { ShortcutTooltip } from '@/components/ui/ShortcutTooltip' import { useEdgeFunctionsQuery } from '@/data/edge-functions/edge-functions-query' import { useIsProjectActive } from '@/hooks/misc/useSelectedProject' import { DOCS_URL, IS_PLATFORM } from '@/lib/constants' import { onSearchInputEscape } from '@/lib/keyboard' import { SHORTCUT_IDS } from '@/state/shortcuts/registry' import type { NextPageWithLayout } from '@/types' const EdgeFunctionsPage: NextPageWithLayout = () => { const router = useRouter() const { ref } = useParams() const showLastHourStats = useFlag('edgeFunctionsRequestMetrics') const isProjectActive = useIsProjectActive() const searchInputRef = useRef(null) const [search, setSearch] = useQueryState('search', parseAsString.withDefault('')) const [sort, setSortQueryParam] = useQueryState( 'sort', parseAsStringLiteral(EDGE_FUNCTIONS_SORT_VALUES).withDefault('name:asc') ) const { data: functions, error, isPending: isLoading, isError, isSuccess, isFetching, refetch, } = useEdgeFunctionsQuery({ projectRef: ref }) useFunctionsListShortcuts({ searchInputRef, setSearch, sort, setSort: setSortQueryParam, canCreateNew: isProjectActive, onCreateNew: () => router.push(`/project/${ref}/functions/new`), onRefresh: () => { refetch() }, }) const filteredFunctions = useMemo(() => { const temp = (functions ?? []).filter((x) => x.name.toLowerCase().includes(search.toLowerCase()) ) const [sortCol, sortOrder] = sort.split(':') as [ EdgeFunctionsSortColumn, EdgeFunctionsSortOrder, ] const orderMultiplier = sortOrder === 'asc' ? 1 : -1 return temp.sort((a, b) => { if (sortCol === 'name') { return a.name.localeCompare(b.name) * orderMultiplier } if (sortCol === 'created_at') { return (a.created_at - b.created_at) * orderMultiplier } if (sortCol === 'updated_at') { return (a.updated_at - b.updated_at) * orderMultiplier } return 0 }) }, [functions, search, sort]) const hasFunctions = (functions ?? []).length > 0 return (
{isLoading && } {isError && (IS_PLATFORM ? ( ) : (

Local functions can be found at briven/functions folder.

))} {isSuccess && ( <> {hasFunctions ? (
} size="tiny" className="w-32 md:w-64" value={search} onChange={(event) => setSearch(event.target.value)} onKeyDown={onSearchInputEscape(search, setSearch)} actions={[ search && (
{search && filteredFunctions.length !== functions.length ? `Viewing ${filteredFunctions.length} of ${functions.length} functions in total` : `Viewing ${functions.length} ${functions.length === 1 ? 'function' : 'functions'} in total`}
Name URL Created Updated {showLastHourStats && ( <> Total requests (1h) 5xx error rate (1h) )} Deployments <> {filteredFunctions.length > 0 ? ( filteredFunctions.map((item) => ( )) ) : (

No results found

Your search for "{search}" did not return any results

)}
) : ( )} )} {!IS_PLATFORM && }
) } EdgeFunctionsPage.getLayout = (page: React.ReactElement) => { return (
Edge Functions Run server-side logic close to your users {IS_PLATFORM && } {page}
) } export default EdgeFunctionsPage